﻿using Digitalmes.Application.Mes;
using Digitalmes.Domain.Mes;
using Digitalmes.Scada.Models;
using Digitalmes.Sugar;

namespace Digitalmes.Scada.Services.Impl;

internal sealed class AlarmService : IAlarmService, ITransientDependency
{
    private readonly SugarRepository<EquipAlarmRecord> _alarmRecordRepo;
    private readonly IEquipAlarmItemQueryService _alarmItemQueryService;

    public AlarmService(SugarRepository<EquipAlarmRecord> alarmRecordRepo,
        IEquipAlarmItemQueryService alarmItemQueryService)
    {
        _alarmRecordRepo = alarmRecordRepo;
        _alarmItemQueryService = alarmItemQueryService;
    }

    public async Task RecordAlarmAsync(AlarmInput input)
    {
        // 对当前警报集合和上一次的警报集合进行对比:
        //  0/1 => 新增警报
        //  1/1 => 不变，表示警报持续中
        //  1/0 => 警报结束，关闭警报
        // 新增警报，先从数据库中查找是否该警报已创建且未关闭（防止因服务重启上一次警报记录丢失导致重复创建）

        List<int> newAlarmNos = [], closedAlarmNos = [];

        // 第一次警报
        if (input.LastAlarms is null || input.LastAlarms.Length == 0)
        {
            for (int i = 0; i < input.NewAlarms.Length; i++)
            {
                if (input.NewAlarms[i])
                {
                    newAlarmNos.Add(i + 1); // 基地址为 1
                }
            }
        }
        else
        {
            for (int i = 0; i < input.NewAlarms.Length; i++)
            {
                bool oldAlarm = input.LastAlarms[i], newAlarm = input.NewAlarms[i]; // 警报数量长度一致
                if (oldAlarm == newAlarm)
                {
                    continue;
                }

                if (!oldAlarm && newAlarm)
                {
                    newAlarmNos.Add(i + 1);
                }
                else if (oldAlarm && !newAlarm)
                {
                    closedAlarmNos.Add(i + 1);
                }
            }
        }

        // 关闭警报
        if (closedAlarmNos.Count != 0)
        {
            // 待关闭的警报
            var closingAlarms = await _alarmRecordRepo.GetListAsync(s => s.LineCode == input.Line 
                && s.EquipName == input.DeviceName 
                && closedAlarmNos.Contains(s.Pos) && s.Status == 1);
            if (closingAlarms.Count > 0)
            {
                closingAlarms.ForEach(s =>
                {
                    s.Close();
                });
                await _alarmRecordRepo.UpdateAsync(closingAlarms, it => new
                {
                    it.Status,
                    it.EndTime,
                    it.Duration,
                });
            }
        }

        // 新警报先在数据库中进行去重
        if (newAlarmNos.Count != 0)
        {
            // 若警报来源于工位（分组）
            string deviceName = input.IsFromTagGroup ? "General" : input.DeviceName!; // 通用
            var alarmItems = await _alarmItemQueryService.GetByNoAsync(deviceName, newAlarmNos);

            // 已创建且未关闭的警报
            List<int> newAlarmsNo = alarmItems.Select(s => s.Pos).ToList();
            var closingAlarms2 = await _alarmRecordRepo.GetListAsync(s => s.LineCode == input.Line 
                && s.EquipName == input.DeviceName
                && newAlarmsNo.Contains(s.Pos) && s.Status == 1);

            // 排除相应的已创建且未关闭的警报
            var alarms0 = alarmItems.Where(s => !closingAlarms2.Any(t => t.Pos == s.Pos))
                .Select(s => new EquipAlarmRecord
                {
                    LineCode = input.Line,
                    LineName = input.Line,
                    EquipCode = "",
                    EquipName = input.DeviceName,
                    Pos = s.Pos,
                    Classify = s.Classify,
                    Content = s.Content,
                    Level = s.Level,
                    StartTime = DateTime.Now,
                    Status = 1,
                }).ToList();

            if (alarms0.Count > 0)
            {
                await _alarmRecordRepo.InsertRangeAsync(alarms0);
            }
        }
    }
}
